//
//  Navigation.m
//  iCan - iPhone Context-Aware Navigation
//  Carnegie Mellon University - 18-842 Distributed Systems
//
//  Created by Andrew Santell on 3/26/12.
//  Copyright (c) 2012 Andrew Santell. All rights reserved.

/* View controller that allows users to select a destination to navigate to */

#import "Navigation.h"
#import "iCanAppDelegate.h"
#import "Hosts.h"
#import "NavResults.h"
#import "SpinnerView.h"
#import "iCanViewController.h"

@interface Navigation ()

@end

@implementation Navigation
@synthesize destName, destIP, result, nodeList, message;
@synthesize pickerView, appDelegate, spinner;
@synthesize inputStream, outputStream;
@synthesize navDetails, badCookie;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    appDelegate = [[UIApplication sharedApplication] delegate];
    destName.inputView = pickerView;
    pickerView.frame = CGRectMake(500, 500, 130, 162);
    
    /* Sort Picker */
    nodeList = [[appDelegate.nodes allKeys] sortedArrayUsingSelector:@selector(compare:)];
    badCookie = FALSE;
}

- (void)viewDidUnload
{
    [self setDestName:nil];
    [self setPickerView:nil];
    [self setDestIP:nil];
    [self setResult:nil];
    [self setNodeList:nil];
    [self setMessage:nil];
    [self setAppDelegate:nil];
    [self setSpinner:nil];
    [self setInputStream:nil];
    [self setOutputStream:nil];
    [self setNavDetails:nil];
    [super viewDidUnload];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

- (IBAction)clBath:(id)sender 
{
    /* Load spinner on top of screen until receiving network result */
    spinner = [[SpinnerView alloc] init];
    [spinner loadSpinnerIntoView:self.view];
    
    /*Populate message to send to server */
    message = @"directions";
    message = [message stringByAppendingString:@";"];
    message = [message stringByAppendingString:appDelegate.nodeName];
    message = [message stringByAppendingString:@";"];
    message = [message stringByAppendingString:appDelegate.myCookie];
    message = [message stringByAppendingString:@";"];
    message = [message stringByAppendingString:@"restroom"];
    message = [message stringByAppendingString:@";"];
    message = [message stringByAppendingString:appDelegate.myName];
    message = [message stringByAppendingString:@";"];
    message = [message stringByAppendingString:@"\n"];
    
    destName.text = @"Closest Restroom";
    
    /* Disable Back button while connecting to network */
    self.navigationController.navigationBar.userInteractionEnabled = NO;
    
    /* Initiate network connection */
    [self initNetworkCommunication];
}

- (IBAction)clPrint:(id)sender 
{
    /* Load spinner on top of screen until receiving network result */
    spinner = [[SpinnerView alloc] init];
    [spinner loadSpinnerIntoView:self.view];
    
    /*Populate message to send to server */
    message = @"directions";
    message = [message stringByAppendingString:@";"];
    message = [message stringByAppendingString:appDelegate.nodeName];
    message = [message stringByAppendingString:@";"];
    message = [message stringByAppendingString:appDelegate.myCookie];
    message = [message stringByAppendingString:@";"];
    message = [message stringByAppendingString:@"printer"];
    message = [message stringByAppendingString:@";"];
    message = [message stringByAppendingString:appDelegate.myName];
    message = [message stringByAppendingString:@";"];
    message = [message stringByAppendingString:@"\n"];
    
    destName.text = @"Closest Printer";
    
    /* Disable Back button while connecting to network */
    self.navigationController.navigationBar.userInteractionEnabled = NO;
    
    /* Initiate network connection */
    [self initNetworkCommunication];
}

- (IBAction)Navigate:(id)sender 
{
    /* Load spinner on top of screen until receiving network result */
    spinner = [[SpinnerView alloc] init];
    [spinner loadSpinnerIntoView:self.view];
    
    /*Populate message to send to server */
    message = @"directions";
    message = [message stringByAppendingString:@";"];
    message = [message stringByAppendingString:appDelegate.nodeName];
    message = [message stringByAppendingString:@";"];
    message = [message stringByAppendingString:appDelegate.myCookie];
    message = [message stringByAppendingString:@";"];
    message = [message stringByAppendingString:destName.text];
    message = [message stringByAppendingString:@";"];
    message = [message stringByAppendingString:appDelegate.myName];
    message = [message stringByAppendingString:@";"];
    message = [message stringByAppendingString:@"\n"];
    
    /* Disable Back button while connecting to network */
    self.navigationController.navigationBar.userInteractionEnabled = NO;
    
    /* Initiate network connection */
    [self initNetworkCommunication];
    
}

-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex   
{
    if (badCookie == TRUE)
    {
        badCookie = FALSE;
        result = NULL;
        iCanViewController *mainScreen = [self.storyboard instantiateViewControllerWithIdentifier:@"MainScreen"];
        [self presentViewController:mainScreen animated:YES completion:nil];
    }
}

- (void) analyzeResult
{
 	/* Set up alert for errors */
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" message:@"You received an error from the network"delegate:nil cancelButtonTitle:nil otherButtonTitles: nil];
    UIAlertView *badCookieAlert = [[UIAlertView alloc] initWithTitle:@"Error" message:@"Your session has expired.  Please login again"delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
    
    /* The server should respond with "ACK" on all good communications */
    NSLog(@"result = %@", result);
    
  
    if ([result isEqualToString:@"NACK"])
    { 
        NSLog(@"Error with received data");
        
        /* Popup alert */
        [alert show];
    }
    else if ([result isEqualToString:@"BAD_COOKIE"])
    { 
        NSLog(@"Bad Cookie");
        badCookie = TRUE;
        [badCookieAlert show];
    }
    
    else 
    {
        NSString *tempResult = [result stringByReplacingOccurrencesOfString:@"\nturn" withString:@"\n\nTurn"];
        NSString *cleanedResult = [tempResult stringByReplacingOccurrencesOfString:@"\nArrive" withString:@"\n\nArrive"];
        navDetails = [self.storyboard instantiateViewControllerWithIdentifier:@"NavDetails"];
        navDetails.srcText = appDelegate.nodeName;
        navDetails.destText = destName.text;
        navDetails.dirText = cleanedResult;
        
        destName.text = nil;
        result = nil; 
        
        [self.navigationController pushViewController:navDetails animated:YES];

    } 
}

-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
    return 1;
}

-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
    return [nodeList count];
}

-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
    return [nodeList objectAtIndex:row];
}

- (void) pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
    NSString *tempString = [nodeList objectAtIndex:row];
    Hosts *host = [appDelegate.nodes objectForKey:tempString];
    
    destName.text = host.name;
    destIP = host.ip;
    
    [destName resignFirstResponder];
}

- (BOOL)textFieldShouldReturn:(UITextField *)theTextField 
{
    [theTextField resignFirstResponder];
    return YES;
}

/* Initiate network connection */
- (void) initNetworkCommunication
{
    CFReadStreamRef readStream = NULL;
    CFWriteStreamRef writeStream = NULL;
    CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef) appDelegate.nodeIP, appDelegate.nodePort, &readStream, &writeStream);
    
    inputStream = (__bridge NSInputStream *) readStream;
    outputStream = (__bridge NSOutputStream *) writeStream;
    
    [inputStream setDelegate:self];
    [outputStream setDelegate:self];
    
    /* Put input and output streams into a run loop */
    [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    
    [inputStream open];
    [outputStream open];
    
    /* Put message into a format that can be sent across the network (NSData) */
    NSData *data = [[NSData alloc] initWithData:[message dataUsingEncoding:NSASCIIStringEncoding]];
    
    /* Send message to network */
    [outputStream write:[data bytes] maxLength:[data length]];
    
    
}

- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent 
{
    /* Create error popup for failed connections */
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" message:@"Could not connect to host"delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
    
    switch (streamEvent) 
    {
		case NSStreamEventOpenCompleted:
			NSLog(@"Stream opened");
			break;
            
            /* Accept return message from network */
		case NSStreamEventHasBytesAvailable:
            
            if (theStream == inputStream) 
            {
                
                uint8_t buffer[1024];
                int len;
                
                while ([inputStream hasBytesAvailable]) 
                {
                    len = [inputStream read:buffer maxLength:sizeof(buffer)];
                    if (len > 0) 
                    {
                        
                        result = [[NSString alloc] initWithBytes:buffer length:len encoding:NSASCIIStringEncoding];
                        
                        if (nil != result) 
                        {
                            NSLog(@"Response: %@", result);
                        }
                    }
                }
            }
			break;			
            
		case NSStreamEventErrorOccurred:
            
            NSLog(@"Can not connect to the host!");
            NSLog(@"Error Result (Should be NULL) = %@", result);
            [inputStream close];
            [inputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
            [outputStream close];
            [outputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
            [spinner removeSpinner];
            [alert show];
            /* Enable Back Button again */
            self.navigationController.navigationBar.userInteractionEnabled = YES;
			break;
            
		case NSStreamEventEndEncountered:
            NSLog(@"Closing Connection");
            [inputStream close];
            [inputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
            [outputStream close];
            [outputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
            self.navigationController.navigationBar.userInteractionEnabled = YES;
            [spinner removeSpinner];
            [self analyzeResult];
			break;
            
		case NSStreamEventHasSpaceAvailable:
            NSLog (@"Output Buffer is Empty");
            break;
            
        default:
			NSLog(@"Unknown event");
            NSLog(@"Error Result (Should be NULL) = %@", result);
            [inputStream close];
            [inputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
            [outputStream close];
            [outputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
            [spinner removeSpinner];
            self.navigationController.navigationBar.userInteractionEnabled = YES;
            [alert show];
	}
}


@end
